package com.fmy.mcsecurity.config.filter;

import com.fmy.mcsecurity.commons.unusual.TokenVerfiyException;
import com.fmy.mcsecurity.login.hander.LoginHandler;
import com.fmy.mcsecurity.token.TokenVerification;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.util.Assert;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author Mr.fmy
 * @version 1.0.0
 * @ClassName JITokenContextFilter
 * @Description TODO token 效验 填充 Filter
 * @createTime 2019/10/23 13:50
 */
@Slf4j
public class JITokenContextFilter extends OncePerRequestFilter {

    private String bearer = "Bearer ";
    private String tokenKey = "Authorization";

    private final TokenVerification tokenVerification;
    private final LoginHandler loginHandler;
    private OrRequestMatcher matcher = null;
    private boolean notMatcher = true; //是否取 matcher 的相反值 true 不取 false 取相反值

    public JITokenContextFilter(TokenVerification tokenVerification, LoginHandler loginHandler) {
        this.tokenVerification = tokenVerification;
        this.loginHandler = loginHandler;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        try {
            String token = request.getHeader(tokenKey);
            token = Strings.isBlank(token) ? request.getParameter(tokenKey) : token;
            if (Strings.isNotBlank(token) && token.startsWith(bearer)) {
                String tokenStr = token.replace(bearer, "");
                SecurityContextHolder.getContext().setAuthentication(tokenVerification.get(tokenStr));
            }
            doFilter(request, response, chain);
        } catch (TokenVerfiyException e) {
            if (matcher != null && matches(request)) {
                //被拦截才抛出异常
                loginHandler.tokenExHander(request, response, e);
            } else {
                doFilter(request, response, chain);
            }
        }
    }

    public void setBearer(String bearer) {
        Assert.hasText(bearer, "bearer parameter must not be empty or null");
        this.bearer = bearer;
    }

    public void setTokenKey(String tokenKey) {
        Assert.hasText(tokenKey, "tokenKey parameter must not be empty or null");
        this.tokenKey = tokenKey;
    }

    public void setMatcher(OrRequestMatcher matcher) {
        this.matcher = matcher;
    }

    public void setNotMatcher(boolean notMatcher) {
        this.notMatcher = notMatcher;
    }

    private boolean matches(HttpServletRequest request) {
        if (notMatcher) {
            return matcher.matches(request);
        } else {
            return !matcher.matches(request);
        }
    }
}
